package com.ermao.learnWebmagic.processor;

import com.alibaba.fastjson.JSON;
import com.ermao.learnWebmagic.entity.UP;
import lombok.extern.slf4j.Slf4j;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Request;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.selector.Json;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;

@Slf4j
public class UPPageProcessor implements PageProcessor {
	private final static String SEARCH_PREFIX = "https://api.bilibili.com/x/web-interface/search";
	private final static String UP_STAT_PREFIX = "https://api.bilibili.com/x/relation/stat";
	private final static String UP_INFO_PREFIX = "https://api.bilibili.com/x/space/acc/info";


	private Site site = Site.me().setRetryTimes(3).setSleepTime(300).setUserAgent("");


	@Override
	public void process(Page page) {

		String curUrl = page.getUrl().toString();

		if (curUrl.startsWith(SEARCH_PREFIX)) {
			// 获取UP 主的 mid 的并且拼接出 UP 主主页 URL
			Json json = page.getJson();
			List<String> midList = json.jsonPath("$.data.result[*].mid").all();
			midList = getUnRepeatableMidList(midList);

			for (String mid : midList) {
				Request UPStatReq = new Request();
				Request UpInfoReq = new Request();
				UP up = new UP();

				UPStatReq.setUrl("https://api.bilibili.com/x/relation/stat?vmid=" + mid + "&jsonp=jsonp");
				UpInfoReq.setUrl("https://api.bilibili.com/x/space/acc/info?mid=" + mid + "&jsonp=jsonp");

				UPStatReq.putExtra("up", up);
				UpInfoReq.putExtra("up", up);

				page.addTargetRequest(UPStatReq);
				page.addTargetRequest(UpInfoReq);
			}

		}


		// 爬取 UP 信息的线
		if (curUrl.startsWith(UP_STAT_PREFIX)) {
			Json json = page.getJson();
			UP up = (UP) page.getRequest().getExtra("up");
			String follower = json.jsonPath("$.data.follower").toString();
			System.out.println("粉丝数量：" + follower);
			up.setFollowers(Integer.parseInt(follower));

			System.out.println(up);
			if (isOver(up)) {
				try {

					try (FileChannel fileChannel = new FileOutputStream("up.json", true).getChannel()) {
						fileChannel.write(Charset.defaultCharset().encode(JSON.toJSONString(up) + ",\n"));
					}

				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} else if (curUrl.startsWith(UP_INFO_PREFIX)) {
			Json json = page.getJson();
			UP up = (UP) page.getRequest().getExtra("up");
			String upName = json.jsonPath("$.data.name").toString();
			String mid = json.jsonPath("$.data.mid").toString();
			up.setUp_name(upName);
			up.setMid(mid);
			if (isOver(up)) {
				try {

					try (FileChannel fileChannel = new FileOutputStream("up.json", true).getChannel()) {
						fileChannel.write(Charset.defaultCharset().encode(JSON.toJSONString(up) + ",\n"));
					}

				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}

	}

	@Override
	public Site getSite() {
		return site;
	}


	// 可以用 Stream 改进
	private List<String> getUnRepeatableMidList(List<String> list) {
		HashSet<String> set = new HashSet<>();
		for (String s : list) {
			if (set.size() >= 20) {
				break;
			}
			set.add(s);
		}

		LinkedList<String> upSpaceURLs = new LinkedList<>(set);
		return upSpaceURLs;
	}


	// 判断对象中属性值是否全不为空
	private boolean isOver(Object item) {
		// 如果 item 的各个字段都不为 null 则表示
		if (null == item) {
			return false;
		}

		try {
			for (Field f : item.getClass().getDeclaredFields()) {
				f.setAccessible(true);


				if (f.get(item) == null) {
					return false;
				}

			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return true;

	}
}
